<?php
/**
 * $string 明文或密文
 * $operation 加密ENCODE或解密DECODE
 * $key 密钥
 * $expiry 密钥有效期 ， 默认是一直有效
 */
function auth_code($string, $operation = 'DECODE', $key = '', $expiry = 0) {
    /*
        动态密匙长度，相同的明文会生成不同密文就是依靠动态密匙
        加入随机密钥，可以令密文无任何规律，即便是原文和密钥完全相同，加密结果也会每次不同，增大破解难度。
        取值越大，密文变动规律越大，密文变化 = 16 的 $ckey_length 次方
        当此值为 0 时，则不产生随机密钥
    */
    $ckey_length = 4;
    $key = md5($key != '' ? $key : md5("TC-NET")); // 此处的key可以自己进行定义，写到配置文件也可以
    $keya = md5(substr($key, 0, 16));

    $keyb = md5(substr($key, 16, 16));
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';

    $cryptkey = $keya.md5($keya.$keyc);
    $key_length = strlen($cryptkey);
    // 明文，前10位用来保存时间戳，解密时验证数据有效性，10到26位用来保存$keyb(密匙b)，解密时会通过这个密匙验证数据完整性
    // 如果是解码的话，会从第$ckey_length位开始，因为密文前$ckey_length位保存 动态密匙，以保证解密正确
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
    $string_length = strlen($string);
    $result = '';
    $box = range(0, 255);

    $rndkey = array();
    for($i = 0; $i <= 255; $i++) {
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
    }
    for($j = $i = 0; $i < 256; $i++) {
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
        $tmp = $box[$i];
        $box[$i] = $box[$j];
        $box[$j] = $tmp;
    }

    for($a = $j = $i = 0; $i < $string_length; $i++) {
        $a = ($a + 1) % 256;
        $j = ($j + $box[$a]) % 256;
        $tmp = $box[$a];
        $box[$a] = $box[$j];
        $box[$j] = $tmp;
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
    }
    if($operation == 'DECODE') {
        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
            return substr($result, 26);
        } else {
            return '';
        }
    } else {
        // 把动态密匙保存在密文里，这也是为什么同样的明文，生产不同密文后能解密的原因
        // 因为加密后的密文可能是一些特殊字符，复制过程可能会丢失，所以用base64编码
        return $keyc.str_replace('=', '', base64_encode($result));
    }

}

function uuid($unique = '') {
    if (!empty($unique)) {
        $chars = md5($unique);
    } else {
        $chars = md5(uniqid(mt_rand(), true));
    }
    $uuid = substr($chars, 0, 8) . '-';
    $uuid .= substr($chars, 8, 4) . '-';
    $uuid .= substr($chars, 12, 4) . '-';
    $uuid .= substr($chars, 16, 4) . '-';
    $uuid .= substr($chars, 20, 12);
    return strtoupper($uuid);
}

/**
 * @desc 通过用户的uuid获得存储用户信息的redis hash表名或者队列名称
 * @param   $uuid
 * @param   $prefix redis key的前缀
 * @param   $nums key个数
 * @param   $bit hash后缀位数，其中$bit必须>=$hashNums的位数
 * @return string hash key
 */
function getHashSubfixByUUID($uuid,$prefix="",$nums = 100,$bit=3)
{
    if(strlen($nums) > $bit){
        return null;
    }
    //1.获取uuid的循环冗余码,并取正整数
    $code = sprintf("%u",crc32($uuid));
    //2.获取hash表后缀
    $format = "%'0".$bit."d";
    $hashSubfix = sprintf($format,($code % $nums));
    return $prefix.$hashSubfix;
}

/**
 * @desc 创建script标签，用于播放视频
 * @param $url
 * @param array $data
 * @return string
 */
function createPlayHtml($url,$isScript = true,$data=[])
{
    $playerUrl = SITE_BASE_URL. "/assets/sewise-player/player/sewise.player.min.js";
    $params = array();
    if (isset($data['title'])) {
        $params['title'] = "";
    }
    $params['autostart'] = isset($data['autostart']) ? $data['autostart'] : "true";
    $params['starttime'] = isset($data['starttime']) ? $data['starttime'] : 0;
    $params['buffer'] = isset($data['buffer']) ? $data['buffer'] : 5;
    $params['skin'] = isset($data['skin']) ? $data['skin'] : "vodWhite";
    $params['topbardisplay'] = isset($data['topbardisplay']) ? $data['topbardisplay'] : "disable";
    $ext = pathinfo($url, PATHINFO_EXTENSION);
    if (in_array($ext, array("flv", "mp4", "m3u8","m4v"))) {
        $params['server'] = "vod";
        $params['type'] = $ext=="m4v"?"mp4":$ext;
        $params['videourl'] = $url;
//        $params["controlbardisplay"] = "disable";
    } else {
        $params['server'] = isset($data['server']) ? $data['server'] : "";
        $params['type'] = isset($data['type']) ? $data['type'] : "";
    }
    $paramsStr = "";
    foreach ($params as $k => $v) {
        $paramsStr .= "{$k}={$v}&";
    }
    $paramsStr = trim($paramsStr, "&");
    $u = $playerUrl . "?" . $paramsStr;
    if($isScript){
        return "<script src='{$u}'></script>";
    }else{
        return $u;
    }

}
 function getImgFromVideo($video, $img, $time = 0) {
    $dirName = dirname($img);
    if (!file_exists($dirName)) {
        exec("mkdir -p {$dirName}");
    }
    $com = "/app/ffmpeg/ffmpeg  -i $video -y -f  image2  -ss {$time} -vframes 1  {$img}";
    passthru($com, $status);
    if ($status == 0 && file_exists($img)) {
        return true;
    } else {
        return false;
    }
}
function getFileAddr($cdnUrl)
{
    $baseUrl = CDN_HOST;
    $len = strlen($baseUrl);
    $suffix = substr($cdnUrl,$len+1);
    $prefixPath = CDN_PATH;
    $path = $prefixPath.$suffix;
    return $path;
}
function getVideoLen($video)
{
    ob_start();
    passthru("/app/ffmpeg/ffmpeg -i $video 2>&1");
    $content = ob_get_clean();
    $pattern = '/Duration:.*(\d{2}:\d{2}:\d{2})/';
    if(preg_match($pattern,$content,$match)){
        $arr = explode(":",$match[1],3);
        $len = $arr[0]*3600+$arr[1]*60+$arr[2];
        return $len;
    }else{
        return 0;
    }
}
function getClientIP()
{
    if (getenv("HTTP_CLIENT_IP"))
        $ip = getenv("HTTP_CLIENT_IP");
    else if(getenv("HTTP_X_FORWARDED_FOR"))
        $ip = getenv("HTTP_X_FORWARDED_FOR");
    else if(getenv("REMOTE_ADDR"))
        $ip = getenv("REMOTE_ADDR");
    else $ip = "Unknow";
    return $ip;
}
function response($code,$msg,$data=[],$count=null)
{
    ob_clean();
    header("Content-type:application/json;");
    echo json_encode(["code"=>$code,"msg"=>$msg,"data"=>$data,"count"=>$count]);
    exit;
}